/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.hiddendanger.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.koron.audit.approval.AfterApprovalService;
import com.koron.audit.domain.Audit;
import com.koron.audit.management.FlowManagement;
import com.koron.audit.mapper.AuditMapper;
import com.koron.common.bean.SecretBean;
import com.koron.common.bean.StaffBean;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.common.stub.Port;
import com.koron.common.web.Util;
import com.koron.hazardsource.util.Immutable;
import com.koron.hiddendanger.bean.HiddenDangerDiscoveryCount;
import com.koron.hiddendanger.domain.CheckRecord;
import com.koron.hiddendanger.domain.PerformancePlan;
import com.koron.hiddendanger.mapper.CheckRecordMapper;
import com.koron.hiddendanger.mapper.HiddenDangerMapper;
import com.koron.hiddendanger.mapper.PerformancePlanMapper;
import com.koron.hiddendanger.service.api.PerformancePlanService;
import com.koron.hiddendanger.uitls.BusinessCode;
import com.koron.system.domain.Message;
import com.koron.system.mapper.MessageMapper;
import com.koron.workflow.bean.MessageEntity;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.swan.bean.MessageBean;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PerformancePlanServiceImpl implements PerformancePlanService, InitializingBean, AfterApprovalService {

    @Value("${app.appid}")
    private String appid;

    @Value("${app.secret}")
    private String secret;

    @Value("${risk_danger_setCode}")
    private String riskDangerSetCode;

    private final static  Logger logger = LoggerFactory.getLogger(PerformancePlanServiceImpl.class);

   private static final String QUARTZ_GROUP = "performancePlan";
    // @Autowired默认按照byType 注入，也就是bean的类型的来传入,
    // 如果需要指定名字，那么需要使@Qualifier("这是bean的名字")
    @Autowired
    private Scheduler scheduler;

    @Autowired
    private FlowManagement flowManagement;

    @Value("${performance_plan}")
    private String planTemplateKey;


    @Override
    public void afterPropertiesSet() throws Exception {
        Map map = flowManagement.getHandlers();
        map.put(PerformancePlanServiceImpl.class.getName(), this);
        scheduler.start();
        try (SessionFactory factory = new SessionFactory()) {
            List<PerformancePlan> plans = factory.getMapper(PerformancePlanMapper.class).queryAllOnUse(2, 1);
            if (null != plans && !plans.isEmpty()) {
                for (PerformancePlan plan : plans) {
                    try {
                        addPlanJob(plan);
                        // 暂停的计划任务
                        if (plan.getUseState() == 0) {
                            pauseJob(plan.getId());
                        }
                        factory.close();
                    } catch (Exception e) {
                        logger.error(e.getMessage(),e);
                    }
                }
            }
        }
    }

    @Override
    public MessageBean<Integer> save(StaffBean user, PerformancePlan plan) {
        MessageBean<Integer> msg = new MessageBean<>();
        SessionFactory factory = new SessionFactory();
        try {
            if (StringUtils.isEmpty(plan.getName())) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_NAME.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_NAME.getDescription());
                return msg;
            }
            if (StringUtils.isEmpty(plan.getCorpCode())) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_CORPCODE.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_CORPCODE.getDescription());
                return msg;
            }
            if (StringUtils.isEmpty(plan.getGridCode())) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_GRIDCODE.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_GRIDCODE.getDescription());
                return msg;
            }
//            if (StringUtils.isEmpty(plan.getPlanCreater())){
//                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_PLANCREATER.getCode());
//                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_PLANCREATER.getDescription());
//                return msg;
//            }
            if (null != plan.getPlanState() && plan.getPlanState() == 1 && StringUtils.isEmpty(plan.getPlanApprover())) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_PLANAPPROVER.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_PLANAPPROVER.getDescription());
                return msg;
            }
            if (StringUtils.isEmpty(plan.getExecutors())) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_EXECUTORS.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_EXECUTORS.getDescription());
                return msg;
            }
//            if (StringUtils.isEmpty(plan.getManager())) {
//                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_MANAGER.getCode());
//                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_MANAGER.getDescription());
//                return msg;
//            }
            if (null == plan.getRepeatType()) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_REPEATTYPE.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_REPEATTYPE.getDescription());
                return msg;
            }
            if (null == plan.getBeginTime()) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_BEGINTIME.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_BEGINTIME.getDescription());
                return msg;
            }
            plan.setFrequency(1);
//            if (null != plan.getEndTime()) {
//                plan.setEndTime(getnowEndTime(plan.getEndTime()));
//            }
            Audit audit = null;
            Integer value = 0;
            if (StringUtils.isEmpty(plan.getId())) {
                //新增
                plan.setAddTime(plan.getUpdateTime());
                plan.setAddUser(plan.getUpdateUser());
                plan.setId(DefaultIdGenerator.getInstance().generateLongId());
                if (null == plan.getPlanState()) {
                    plan.setPlanState(1);
                }
                plan.setUseState(0);
                plan.setRemoved(0);
                plan.setPlanCreater(user.getCode() + "_" + user.getUserid());
                plan.setPlanCreaterName(user.getName() + "_" + user.getDepartmentname());
//                List<DeptBean> departmentTreeBeanList = getPort().dept(user.getCode()).getData();
//                if(null!=departmentTreeBeanList&&departmentTreeBeanList.size()>0){
//                    plan.setPlanCreater(user.getCode() + "_" + user.getUserid());
//                    plan.setPlanCreaterName(departmentTreeBeanList.get(0).getName());
//                    factory.getMapper(PerformancePlanMapper.class).insert(plan);
//                }
                if (plan.getPlanState() == 1) {
                    audit = new Audit();
                    audit.setTitle("新增计划：" + plan.getName());
                    audit.setFlowName(Immutable.ADD_PERFORMANCEPLAN);
                }
                value = factory.getMapper(PerformancePlanMapper.class).insert(plan);
            } else {
                //修改
                PerformancePlan en = queryOne(plan.getId()).getData();
                if (null == en) {
                    msg.setCode(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getCode());
                    msg.setDescription(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getDescription());
                    return msg;
                }
                if (en.getPlanState() == 1) {
                    msg.setCode(BusinessCode.PERFORMANCEPLAN_IS_PROCESSING.getCode());
                    msg.setDescription(BusinessCode.PERFORMANCEPLAN_IS_PROCESSING.getDescription());
                    return msg;
                }
                if (en.getPlanState() == 4) {
                    msg.setCode(BusinessCode.PERFORMANCEPLAN_IS_DISCDRD.getCode());
                    msg.setDescription(BusinessCode.PERFORMANCEPLAN_IS_DISCDRD.getDescription());
                    return msg;
                }
//                plan.setPlanState(1);
                plan.setPlanCreater(en.getPlanCreater());
                plan.setPlanCreaterName(en.getPlanCreaterName());
                if (plan.getPlanState() == 1) {
                    audit = new Audit();
                    if (en.getPlanState() == 0 || en.getPlanState() == 3) {
                        audit.setTitle("新增计划：" + plan.getName());
                        audit.setFlowName(Immutable.ADD_PERFORMANCEPLAN);
                    } else {
                        audit.setTitle("修改计划：" + plan.getName());
                        audit.setFlowName(Immutable.UPDATE_PERFORMANCEPLAN);
                    }
                }
                value = factory.getMapper(PerformancePlanMapper.class).update(plan);
            }
            if (null == audit) {
                if (value > 0) {
                    factory.close();
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("检查计划保存成功");
                    return msg;
                } else {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("检查计划保存失败");
                    return msg;
                }
            } else {
                audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                audit.setUpdateUser(plan.getUpdateUser());
                audit.setUpdateTime(plan.getUpdateTime());
                audit.setAddTime(plan.getUpdateTime());
                audit.setAddUser(plan.getUpdateUser());
                audit.setFlowType(2);
                audit.setOperation(1);
                audit.setTarget(PerformancePlanServiceImpl.class.getName());
                audit.setCorpCode(plan.getCorpCode());
                audit.setBusinessIds(plan.getId());
                audit.setInitiatorCode(plan.getPlanCreater().split("_")[0]);
                audit.setDescription(StringUtils.isNotEmpty(plan.getDescription()) ? plan.getDescription() : "检查计划流程");
                audit.setState(1);
                audit.setTemplateKey(planTemplateKey);
                audit.setInitiatorAccount(user.getUserid());
                audit.setSetCode(riskDangerSetCode);
                audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                Map<String, Object> businessDataMap = new HashMap<>();
                //根据选中人的code,查询对应userid
//            String planApproverCode=plan.getPlanApprover().split("_")[0];
//            List<StaffBean> staffBeanList= (List<StaffBean>) util.staff(planApproverCode,0).getData();
//            if(null==staffBeanList){
//                msg.setCode(BusinessCode.FAILURE.getCode());
//                msg.setDescription("选中的计划审批人不存在或已离职");
//                return msg;
//            }
                businessDataMap.put("planApprover", plan.getPlanApprover().split("_")[1]);
                if (!flowManagement.initFlow(user, audit, businessDataMap)) {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("提交检查计划失败");
                    return msg;
                } else {
                    factory.close();
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("提交检查计划成功");
                    return msg;
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            if (null != factory) {
                factory.close(false);
            }
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        } finally {
            factory.close();
        }
    }


    /**
     * 批量提交检查计划
     *
     * @param user
     * @param corpCode
     * @param title
     * @param note
     * @param approval
     * @param performancePlanIds
     * @return
     */
    @Override
    public MessageBean<Integer> batchCommit(StaffBean user, String corpCode, String title, String note, String approval, String performancePlanIds) {
        MessageBean<Integer> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), Integer.class);
        SessionFactory factory = null;
        try {
            factory = new SessionFactory();
            List<String> idLists = Arrays.asList(performancePlanIds.split("[,，]"));
            if (null == idLists || idLists.size() == 0) {
                msg.setCode(BusinessCode.PARAM_NOT_EMPTY.getCode());
                msg.setDescription("未选中数据");
                return msg;
            }
            PerformancePlanMapper mapper = factory.getMapper(PerformancePlanMapper.class);
            // 获取检查计划数据并检查是否为草稿状态
            List<PerformancePlan> plans = mapper.getPlanByIds(idLists);
            for (PerformancePlan plan : plans) {
                if (plan.getPlanState() != 0 && plan.getPlanState() != 3) {
                    msg.setCode(BusinessCode.DANGER_IS_COMMITED.getCode());
                    msg.setDescription("选中的数据包含已经提交即非草稿状态的数据，无法执行提交操作");
                    return msg;
                }
            }
            // 更新计划状态
            Integer value = mapper.updatePlanState(1, idLists);
            if (value > 0) {
                Audit audit = new Audit();
                audit.setTitle(StringUtils.isEmpty(title) ? "新增检查计划" : title);
                audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                audit.setUpdateUser(user.getName());
                audit.setUpdateTime(new Date());
                audit.setAddTime(new Date());
                audit.setAddUser(user.getName());
                audit.setFlowType(2);
                audit.setFlowName(Immutable.ADD_PERFORMANCEPLAN);
                audit.setOperation(1);
                audit.setTarget(PerformancePlanServiceImpl.class.getName());
                audit.setCorpCode(StringUtils.isEmpty(corpCode) ? plans.get(0).getCorpCode() : corpCode);
                audit.setBusinessIds(performancePlanIds);
                audit.setInitiatorCode(user.getCode());
                audit.setDescription(StringUtils.isEmpty(note) ? "安全检查计划流程" : note);
                audit.setState(1);
                audit.setTemplateKey(planTemplateKey);
                audit.setInitiatorAccount(user.getUserid());
                audit.setSetCode(riskDangerSetCode);
                audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                Map<String, Object> businessDataMap = new HashMap<>();
                businessDataMap.put("planApprover", approval.split("_")[1]);
                if (!flowManagement.initFlow(user, audit, businessDataMap)) {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("流程启动失败");
                    return msg;
                } else {
                    factory.close();
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("提交检查计划成功");
                    return msg;
                }
            } else {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("提交检查计划失败");
                return msg;
            }
        } catch (Exception e) {
            if (null != factory) {
                factory.close(false);
            }
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("提交失败");
            return msg;
        } finally {
            if (null != factory) {
                factory.close();
            }
        }
    }

    @Override
    public MessageBean<List<PerformancePlan>> getBusinessData(String businessIds) {
        MessageBean<List<PerformancePlan>> msg = new MessageBean();
        SessionFactory factory = null;
        try {
            factory = new SessionFactory();
            List<String> idLists = Arrays.asList(businessIds.split("[,，]"));
            PerformancePlanMapper mapper = factory.getMapper(PerformancePlanMapper.class);
            // 获取检查计划数据
            List<PerformancePlan> plans = mapper.getPlanByIds(idLists);
            msg.setData(plans);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription(BusinessCode.SUCCESS.getDescription());
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription(BusinessCode.FAILURE.getDescription());
            return msg;
        } finally {
            if (null != factory) {
                factory.close();
            }
        }
    }

    @Override
    public List<PerformancePlan> exportList(StaffBean user, String corpCode, String name, String planCreater, String gridCode, String executors, Integer useState, Integer repeatType) {
        try (SessionFactory factory = new SessionFactory()) {
            List<PerformancePlan> list = factory.getMapper(PerformancePlanMapper.class).queryByCondition(user.getCode(),name, planCreater, corpCode, gridCode,
                    executors, null, useState, repeatType, null, null);
            List<String> planIds = new ArrayList<>();
            list.forEach(p -> {
                planIds.add(p.getId());
            });
            List<HiddenDangerDiscoveryCount> hiddenDangerDiscoveryCount = factory.getMapper(HiddenDangerMapper.class).getHiddenDangerDiscoveryCount(planIds);
            Map<String, Map<String, List<CheckRecord>>> managerNameMap = factory.getMapper(CheckRecordMapper.class).queryCheckRecordByPlanIds(planIds).
                    stream().collect(Collectors.groupingBy(p -> p.getPlanId(), Collectors.groupingBy(p -> p.getManagerName())));
            Map<String, Integer> countMap = hiddenDangerDiscoveryCount.
                    stream().collect(Collectors.toMap(p -> p.getPlanId(), p -> p.getCount()));
            if (null != list && list.size() > 0) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                list.forEach(bean -> {
                    StringBuffer sb = new StringBuffer();
                    if (null != bean.getBeginTime() && null != bean.getEndTime()) {
                        sb.append(sdf.format(bean.getBeginTime())).append("至").append(sdf.format(bean.getEndTime()));
                        bean.setTime(sb.toString());
                    }
                    if (StringUtils.isNotEmpty(bean.getExecutorsName())) {
                        bean.setExecutorsName(JSONObject.parseArray(bean.getExecutorsName(), String.class).stream().collect(Collectors.joining(",")));
                    }
                    if (managerNameMap.containsKey(bean.getId())){
                        Map<String, List<CheckRecord>> stringListMap = managerNameMap.get(bean.getId());
                        StringBuilder sb1 = new StringBuilder();
                        Set<String> checkRecordManagerName = stringListMap.keySet();
                        int i = 0;
                        for(String managerName : checkRecordManagerName){
                            sb1.append(managerName);
                            if(i != checkRecordManagerName.size()-1){
                                sb1.append(",");
                            }
                            i++;
                        }
                        bean.setCheckRecordManagerName(sb1.toString());
                    }else{
                        bean.setCheckRecordManagerName("");
                    }
                    if(countMap.containsKey(bean.getId())){
                        bean.setHiddenDangerDiscoveryCount(countMap.get(bean.getId()));
                    }else{
                        bean.setHiddenDangerDiscoveryCount(0);
                    }
                });
            }
            factory.close();
            return list;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return null;
        }
    }

    @Override
    public MessageBean<DataBean<PerformancePlan>> queryByCondition(StaffBean user, String name, String planCreater, String corpCode, String gridCode, String executors, Integer planState, Integer useState, Integer repeatType, Integer start, Integer rows) {
        MessageBean<DataBean<PerformancePlan>> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            List<PerformancePlan> list = factory.getMapper(PerformancePlanMapper.class).queryByCondition(user.getCode(), name, planCreater, corpCode, gridCode,
                    executors, planState, useState, repeatType, start, rows);
            Integer totalNumber = factory.getMapper(PerformancePlanMapper.class).countByCondition(user.getCode(), name, planCreater, corpCode, gridCode, executors, planState, useState, repeatType);
            rows = rows == null ? totalNumber : (rows <= 0 ? 1 : rows);
            Integer totalPage = totalNumber > rows ? (totalNumber % rows == 0 ? totalNumber / rows : totalNumber / rows + 1) : 1;
            DataBean<PerformancePlan> dataBean = new DataBean<>();
            dataBean.setTotalNumber(totalNumber);
            dataBean.setTotalPage(totalPage);
            dataBean.setPageSize(rows);
            dataBean.setList(list);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription("查询检查记录列表成功");
            msg.setData(dataBean);
            factory.close();
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<PerformancePlan> queryOne(String id) {
        MessageBean<PerformancePlan> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            if (StringUtils.isEmpty(id)) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getDescription());
                return msg;
            }
            PerformancePlan plan = factory.getMapper(PerformancePlanMapper.class).queryOne(id);
            //getNames(plan);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription("获取检查计划详情成功");
            msg.setData(plan);
            factory.close();
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<Integer> dummyRemove(StaffBean user, String id) {
        MessageBean<Integer> msg = new MessageBean<>();
        SessionFactory factory = new SessionFactory();
        try {
            if (StringUtils.isEmpty(id)) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getDescription());
                return msg;
            }
            PerformancePlan plan = queryOne(id).getData();
            if (null == plan) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getDescription());
                return msg;
            }
            if (plan.getUseState() == 1 || plan.getPlanState() == 1) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_IS_PROCESSING.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_IS_PROCESSING.getDescription());
                return msg;
            }
            if (plan.getPlanState() == 0) {
                Integer delete = factory.getMapper(PerformancePlanMapper.class).delete(id);
                if (delete > 0) {
                    factory.close();
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("删除检查计划成功");
                    msg.setData(1);
                    return msg;
                } else {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("删除检查计划失败");
                    msg.setData(1);
                    return msg;
                }
            }
            if (plan.getPlanState() == 4 || plan.getPlanState() == 3) {
                factory.getMapper(PerformancePlanMapper.class).dummyRemove(id);
                factory.close();
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("删除检查计划成功");
                msg.setData(1);
                return msg;
            }
            if (plan.getPlanState() == 2) {
                if (StringUtils.isEmpty(plan.getPlanApprover())) {
                    factory.getMapper(PerformancePlanMapper.class).dummyRemove(id);
                    factory.close();
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("删除检查计划成功");
                    msg.setData(1);
                    return msg;
                } else {
                    //将要删除的计划交由审批人审批，审批通过之后才能执行删除操作
                    plan.setPlanState(3);
                    factory.getMapper(PerformancePlanMapper.class).update(plan);
                    Audit audit = new Audit();
                    Date date = new Date();
                    audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                    audit.setUpdateUser(user.getName());
                    audit.setUpdateTime(date);
                    audit.setAddTime(date);
                    audit.setAddUser(user.getName());
                    audit.setFlowType(1);
                    audit.setFlowName(Immutable.DELETE_PERFORMANCEPLAN);
                    audit.setOperation(2);
                    audit.setTarget(PerformancePlanServiceImpl.class.getName());
                    audit.setTitle(plan.getName());
                    audit.setCorpCode(plan.getCorpCode());
                    audit.setBusinessIds(plan.getId());
                    audit.setInitiatorCode(user.getCode());
                    audit.setDescription(plan.getDescription());
                    audit.setState(1);
                    audit.setTemplateKey(planTemplateKey);
                    audit.setInitiatorAccount(user.getUserid());
                    audit.setSetCode(riskDangerSetCode);
                    audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                    Map<String, Object> businessDataMap = new HashMap<>();
//                    String planApproverCode=plan.getPlanApprover().split("_")[0];
//                    StaffBean staffBean= (StaffBean) util.staff(planApproverCode,1).getData();
//                    if(null==staffBean||staffBean.getStatus()==1){
//                        msg.setCode(BusinessCode.FAILURE.getCode());
//                        msg.setDescription("选中的计划审批人不存在或已离职");
//                    }
                    businessDataMap.put("planApprover", plan.getPlanApprover().split("_")[1]);
                    if (!flowManagement.initFlow(user, audit, businessDataMap)) {
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("提交检查计划删除审批失败");
                        return msg;
                    } else {
                        factory.close();
                        msg.setCode(BusinessCode.SUCCESS.getCode());
                        msg.setDescription("提交检查计划删除审批成功");
                        return msg;
                    }
                }
            }
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription(BusinessCode.FAILURE.getDescription());
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            if (null != factory) {
                factory.close(false);
            }
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        } finally {
            if (null != factory) {
                factory.close();
            }
        }
    }

    /**
     * 获取用户是执行人
     *
     * @param cropCode
     * @param userCode
     * @return
     */
    @Override
    public MessageBean<List<PerformancePlan>> queryAll(String cropCode, String userCode) {
        MessageBean<List<PerformancePlan>> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            // 2021-6-30 取消单位关联，只查询执行人有当前用户的检查计划
            List<PerformancePlan> list = factory.getMapper(PerformancePlanMapper.class).queryByCondition(userCode, null, null, null, null,
                    userCode, 2, 1, null, null, null);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription("查询检查记录列表成功");
            msg.setData(list);
            factory.close();
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<Boolean> pausePlan(String id) {
        MessageBean<Boolean> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            if (StringUtils.isEmpty(id)) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getDescription());
                return msg;
            }
            PerformancePlan plan = queryOne(id).getData();
            if (null == plan) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getDescription());
                return msg;
            }
            PerformancePlanMapper mapper = factory.getMapper(PerformancePlanMapper.class);
            // 当计划任务在运行中才能暂停
            if (null != plan && plan.getUseState() == 1) {
                plan.setUseState(0);
                plan.setUpdateTime(new Date());
                if (mapper.update(plan) > 0) {
                    pauseJob(id);
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("计划暂停成功");
                    factory.close();
                    return msg;
                } else {
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("计划暂停失败");
                    factory.close(false);
                    return msg;
                }
            } else {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_IS_PAUSE.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_IS_PAUSE.getDescription());
                factory.close();
                return msg;
            }
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<Boolean> resumePlan(String id) {
        MessageBean<Boolean> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            if (StringUtils.isEmpty(id)) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_EMPTY_CHANGE_DATA.getDescription());
                factory.close();
                return msg;
            }
            PerformancePlan plan = queryOne(id).getData();
            if (null == plan) {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_NOT_EXISIT.getDescription());
                factory.close();
                return msg;
            }
            PerformancePlanMapper mapper = factory.getMapper(PerformancePlanMapper.class);
            // 当计划任务在运行中才能暂停
            if (null != plan && plan.getUseState() == 0) {
                plan.setUseState(1);
                plan.setUpdateTime(new Date());
                if (mapper.update(plan) > 0) {
                    resumeJob(id);
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("计划重新启动成功");
                    factory.close();
                    return msg;
                } else {
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("计划重新启动失败");
                    factory.close(false);
                    return msg;
                }
            } else {
                msg.setCode(BusinessCode.PERFORMANCEPLAN_IS_RUNNING.getCode());
                msg.setDescription(BusinessCode.PERFORMANCEPLAN_IS_RUNNING.getDescription());
                factory.close();
                return msg;
            }
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<DataBean<PerformancePlan>> appList(String code, Integer start, Integer rows) {
        MessageBean<DataBean<PerformancePlan>> msg = new MessageEntity<>();
        try (SessionFactory factory = new SessionFactory()) {
            String simpleCode = code.split("_")[0];
            List<PerformancePlan> list = factory.getMapper(PerformancePlanMapper.class).appList(code, simpleCode, start, rows);
            Integer totalNumber = factory.getMapper(PerformancePlanMapper.class).countAppList(code, simpleCode);
            rows = rows == null ? totalNumber : (rows <= 0 ? 1 : rows);
            Integer totalPage = totalNumber > rows ? (totalNumber % rows == 0 ? totalNumber / rows : totalNumber / rows + 1) : 1;
            DataBean<PerformancePlan> dataBean = new DataBean<>();
            dataBean.setList(list);
            dataBean.setTotalNumber(totalNumber);
            dataBean.setTotalPage(totalPage);
            dataBean.setPageSize(rows);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription("获取列表成功");
            msg.setData(dataBean);
            factory.close();
            return msg;
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<DataBean<PerformancePlan>> indexPerformancePlanList(String code, Integer start, Integer rows) {
        MessageBean<DataBean<PerformancePlan>> msg = new MessageEntity<>();
        try (SessionFactory factory = new SessionFactory()) {
            String simpleCode = code.split("_")[0];
            List<PerformancePlan> list = factory.getMapper(PerformancePlanMapper.class).indexPerformancePlanList(code, simpleCode, start, rows);
            Integer totalNumber = factory.getMapper(PerformancePlanMapper.class).countIndexPerformancePlanList(code, simpleCode);
            rows = rows == null ? totalNumber : (rows <= 0 ? 1 : rows);
            Integer totalPage = totalNumber > rows ? (totalNumber % rows == 0 ? totalNumber / rows : totalNumber / rows + 1) : 1;
            DataBean<PerformancePlan> dataBean = new DataBean<>();
            dataBean.setList(list);
            dataBean.setTotalNumber(totalNumber);
            dataBean.setTotalPage(totalPage);
            dataBean.setPageSize(rows);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription("获取列表成功");
            msg.setData(dataBean);
            factory.close();
            return msg;
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }


    /**
     * a single job can be associated with multiple triggers. the pauseJob
     * method simply retrieves all triggers associated with the specified job
     * and pauses them, whereas the pauseTrigger method pauses only a particular
     * trigger. pausing a job in Quartz does not pause a currently running job,
     * it merely prevents the job from being run in the future
     *
     * @param bean
     * @throws Exception
     */
    private void addPlanJob(PerformancePlan bean) {
        if (null != bean.getEndTime()) {
            bean.setEndTime(getnowEndTime(bean.getBeginTime()));
        }
        try {
            if (!scheduler.checkExists(JobKey.jobKey(bean.getId(), QUARTZ_GROUP))) {
                // 单次执行如果misfire了，重新补上继续生成
                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
                        .cronSchedule(getCornExpression(bean.getRepeatType(), bean.getBeginTime()));
                if (bean.getRepeatType() != 5) {
                    cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
                }
                JobDetail job = JobBuilder.newJob(PerformancePlanJob.class).withIdentity(bean.getId(), QUARTZ_GROUP)
                        .usingJobData("id", bean.getId()).build();
                Trigger trigger = TriggerBuilder.newTrigger()
                        .startAt(bean.getRepeatType() == 5 ? new Date()
                                : (bean.getBeginTime() == null ? new Date() : bean.getBeginTime()))
                        .endAt(bean.getEndTime() == null ? null : bean.getEndTime())
                        .withIdentity(bean.getId(), QUARTZ_GROUP).withSchedule(cronScheduleBuilder).build();
                // Tell quartz to schedule the job using our trigger
                scheduler.scheduleJob(job, trigger);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
    }

    public void pauseJob(String id) throws Exception {
        scheduler.pauseJob(JobKey.jobKey(id, QUARTZ_GROUP));
        scheduler.pauseTrigger(TriggerKey.triggerKey(id, QUARTZ_GROUP));
    }

    public void resumeJob(String id) throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey(id, QUARTZ_GROUP));
        scheduler.resumeTrigger(TriggerKey.triggerKey(id, QUARTZ_GROUP));
    }

    private String getCornExpression(Integer repeatType, Date checkTime) {

        //秒 分钟 小时 日期 月份 星期 年份 * 可用在所有字段中，表示对应时间域的每一个时刻，例如， 在分钟字段时，表示“每分钟” ?；该字符只在日期和星期字段中使用，它通常指定为“无意义的值”，相当于点位符
        Calendar calendar = java.util.Calendar.getInstance();
        Calendar calendar1 = java.util.Calendar.getInstance();
        Calendar calendar2 = java.util.Calendar.getInstance();
        calendar.setTime(checkTime);
        calendar2.setTime(checkTime);
        // 提前5天生成
        calendar.add(Calendar.DAY_OF_MONTH, -5);
        if (calendar.before(calendar1)) {
            calendar.setTime(calendar1.getTime());
        }
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int month = calendar.get(Calendar.MONTH) + 1;
        int week = calendar.get(Calendar.DAY_OF_WEEK);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        StringBuffer sb = new StringBuffer();
        switch (repeatType) {
            // 0:每周,1:每月,2:每季度,3:每半年,4:每年 5:单次  6:每天
            case 0:
                int weekDay = week;
                if (calendar2.before(calendar1)) {
                    weekDay = weekDay + 1;
                }
                sb.append("0 0 0 ? * ").append(weekDay);
                // sb.append("*/35 * * * * ?");
                return sb.toString();
            case 1:
                // 每月生成的任务在月底时为了避免闰年，或是某个不存在的天数，统一在28号
                if (day > 28) {
                    day = 28;
                }
                if (calendar2.before(calendar1)) {
                    day = day + 1;
                }
                sb.append("0 0 0 ").append(day).append(" * ?");
                return sb.toString();
            case 2:
                // 避免每个月31号生成，4月没有31号
                if (day > 30) {
                    day = 30;
                }
                if (calendar2.before(calendar1)) {
                    day = day + 1;
                }
                sb.append("0 0 0 ").append(day).append(" 1,4,7,10 ?");
                return sb.toString();
            case 3:
                if (calendar2.before(calendar1)) {
                    day = day + 1;
                }
                sb.append("0 0 0 ").append(day).append(" 1,7 ?");
                return sb.toString();
            case 4:
                if (calendar2.before(calendar1)) {
                    day = day + 1;
                }
                sb.append("0 0 0 ").append(day).append(" ").append(month).append("? *");
                return sb.toString();
            case 5:
                if (calendar2.before(calendar1)) {
                    sb.append("59 59 ").append(hour).append(" ").append(day).append(" ").append(month).append(" ? *");
                } else {
                    sb.append("0 0 0 ").append(day).append(" ").append(month).append(" ? *");
                }
                return sb.toString();
            case 6:
                if (calendar2.before(calendar1)) {
                    sb.append("59 59 ").append(hour).append(" ").append(" * * ? *");
                } else {
                    sb.append("0 0 0 ").append(" * * ? *");
                }
                return sb.toString();
            default:
                return null;
        }
    }


    public Port getPort() {
        SecretBean secretBean = new SecretBean();
        secretBean.setAppid(appid);
        secretBean.setSecret(secret);
        return new Port(secretBean);
    }

    @Override
    public void editApproval(Audit audit) {
        SessionFactory factory = new SessionFactory();
        List<PerformancePlan> planList = new ArrayList<>();
        try {
            String planIds = audit.getBusinessIds();
            if (StringUtils.isNotEmpty(planIds)) {
                String[] ids = planIds.split("[,，]");
                for (String planId : ids) {
                    PerformancePlan plan = queryOne(planId).getData();
                    if (null != plan) {
                        planList.add(plan);
                        PerformancePlanMapper planMapper = factory.getMapper(PerformancePlanMapper.class);
                        plan.setPlanState(2);
                        plan.setUseState(1);
                        if (planMapper.update(plan) > 0) {
                            audit.setState(2);
                            factory.getMapper(AuditMapper.class).update(audit);
                            // 发送系统内部消息
                            sendInnerMessage(factory, plan);
                        }
                    }
                }
            }
            factory.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            if (null != factory) {
                factory.close(false);
            }
        } finally {
            if (null != planList && planList.size() > 0) {
                planList.forEach(plan -> addPlanJob(plan));
            }
            if (null != factory) {
                factory.close();
            }
        }
    }

    /**
     * 发送系统内部消息
     *
     * @param factory
     * @param plan
     */
    private void sendInnerMessage(SessionFactory factory, PerformancePlan plan) {
        try {
            if (null != plan) {
                List<String> checkExecutors = JSONObject.parseArray(plan.getExecutors(), String.class);
                List<Message> messageList = new ArrayList<>();
                for (String checkExecutor : checkExecutors) {
                    Message message = new Message();
                    Date time = new Date();
                    message.setId(DefaultIdGenerator.getInstance().generateLongId());
                    message.setAddTime(time);
                    message.setIsRemove(0);
                    message.setIsRead(0);
                    message.setAddUser(plan.getAddUser());
                    message.setUpdateUser(plan.getUpdateUser());
                    message.setUpdateTime(time);
                    message.setTitle("您有一项新的安全检查任务");
                    message.setId(DefaultIdGenerator.getInstance().generateLongId());
                    message.setContent("根据检查计划名称为：" + plan.getName() + "，您有一项新的检查任务");
                    message.setReceiverCode(checkExecutor.split("_")[0]);
                    messageList.add(message);
                }
                if (null != messageList && messageList.size() > 0) {
                    factory.getMapper(MessageMapper.class).batchInsert(messageList);
                }
                factory.close();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
    }

    @Override
    public void discardApproval(Audit audit) {
        SessionFactory factory = new SessionFactory();
        try {
            String planId = audit.getBusinessIds();
            if (StringUtils.isNotEmpty(planId)) {
                PerformancePlan plan = queryOne(planId).getData();
                if (null != plan) {
                    plan.setUseState(0);
                    PerformancePlanMapper mapper = factory.getMapper(PerformancePlanMapper.class);
                    if (mapper.dummyRemove(planId) > 0) {
                        scheduler.deleteJob(JobKey.jobKey(planId, QUARTZ_GROUP));
                        audit.setState(2);
                        factory.getMapper(AuditMapper.class).update(audit);
                    }
                }
            }
            factory.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            if (null != factory) {
                factory.close(false);
            }
        }
    }

    @Override
    public void processDiscard(Audit audit) {
        SessionFactory factory = new SessionFactory();
        try {
            String planId = audit.getBusinessIds();
            if (StringUtils.isNotEmpty(planId)) {
                PerformancePlan plan = queryOne(planId).getData();
                if (null != plan) {
                    if (plan.getPlanState() == 1) {
                        if (audit.getFlowName().equals(Immutable.ADD_PERFORMANCEPLAN)) {
                            plan.setPlanState(0);
                        }
                        if (audit.getFlowName().equals(Immutable.UPDATE_PERFORMANCEPLAN)) {
                            plan.setPlanState(3);
                        }
                    }
                }
                if (Immutable.DELETE_PERFORMANCEPLAN.equals(audit.getFlowName())) {
                    //删除检查计划审批流程被废弃
                    plan.setPlanState(2);
                    plan.setUseState(0);
                }
                factory.getMapper(PerformancePlanMapper.class).update(plan);
            }
            factory.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            if (null != factory) {
                factory.close(false);
            }
        }

    }

    private Date getnowEndTime(Date date) {
        if (null != date) {
            Calendar todayEnd = Calendar.getInstance();
            todayEnd.setTime(date);
            todayEnd.set(Calendar.HOUR_OF_DAY, 23);
            todayEnd.set(Calendar.MINUTE, 59);
            todayEnd.set(Calendar.SECOND, 59);
            todayEnd.set(Calendar.MILLISECOND, 999);
            return todayEnd.getTime();
        } else {
            return null;
        }
    }

    @Override
    public void reject(Audit audit, List<String> userIdList) {
        // TODO 流程驳回操作
    }

    @Override
    public void passApproval(Integer operation, Audit audit) {
        // TODO 流程提交成功操作
    }
}
